package beanstao.util.id;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import beanstao.util.Sber;

import com.google.common.collect.Lists;

/**
 * 针对枚举类型(例如“角色”，“卡类型”，“业务类型”，“窗口类型”等)的实体的ID的封装。<br>
 * 鉴于太常用，本类型的命名使用了缩写(全称Enum Id)。<br>
 * 一般使用可以以 EId.Me("") 的方式。<br>
 * <b>在一个项目中可以容纳共不到1700万的ID。本类型的ID一般会采用从 1024 至 16777215 的整数范围。</b>
 * 
 * @author beanstao@google.com 
 */
public final class EId implements Id
{
	public static void main(String[] args)
	{

	}

	/**
	 * ID的最大值。2的24次方。共不到1700万的ID，一般来讲是够用的。
	 */
	public static final int MAX = 16777215;
	/**
	 * ID的最小值。2的10次方。
	 */
	public static final int MIN = 1024;
	/**
	 * 已经使用的ID值的集合
	 */
	private static List<Integer> alreadyUsedList = Lists.newLinkedList();

	/**
	 * 将已使用的ID值集合传入，可多次调用，内部机制是向一个静态的集合中<B>追加</B>。
	 * 
	 * @param list
	 */
	public static void initializes(ArrayList<Integer> list)
	{
		if ((null != list) && (list.size() > 0))
		{
			alreadyUsedList.addAll(list);
			Collections.sort(alreadyUsedList);
		}
	}

	/**
	 * 得到一个创建好值的本类型实例
	 * 
	 * @return
	 */
	public static Id ME()
	{
		int id = 1024;
		if (alreadyUsedList.size() > 0)
			id = alreadyUsedList.get(alreadyUsedList.size() - 1) + 1;
		alreadyUsedList.add(id);
		return new EId(id);
	}

	/**
	 * 得到一个创建好值的本类型实例
	 * 
	 * @return
	 */
	public static Id ME(int id)
	{
		if ((id < EId.MIN) || (id > EId.MAX))
			throw new IllegalArgumentException(EId.class.getSimpleName() + " >>> ID值越界。");
		if (!alreadyUsedList.contains(id))
		{
			if (alreadyUsedList.size() > 0)
				id = alreadyUsedList.get(alreadyUsedList.size() - 1) + 1;
			alreadyUsedList.add(id);
		}
		return new EId(id);
	}

	/**
	 * 得到一个创建好值的本类型实例
	 * 
	 * @return
	 */
	public static Id ME(String id)
	{
		int intId = alreadyUsedList.size();
		try
		{
			intId = Integer.parseInt(id);
		}
		catch (NumberFormatException e)
		{
			throw e;
		}
		return ME(intId);
	}

	private EId(int id)
	{
		_Id = id;
	}

	private int _Id = 1024;

	public int getId()
	{
		return _Id;
	}

	@Override
	public String toXPath()
	{
		Sber sber = Sber.ME();
		return sber.append("[@").append("id='").append(String.valueOf(_Id)).append("']").toString();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see beanstao.util.store.domainobject.base.Id#toString()
	 */
	@Override
	public String toString()
	{
		return String.valueOf(_Id);
	}

	@Override
	public int hashCode()
	{
		final int prime = 31;
		int result = 1;
		result = prime * result + _Id;
		return result;
	}

	@Override
	public boolean equals(Object obj)
	{
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (this.getClass() != obj.getClass())
			return false;
		EId other = (EId) obj;
		if (_Id != other._Id)
			return false;
		return true;
	}

}
